#include "ast.h"

#include <cstdio>

using namespace std;

typedef list<pair<string, string> > PairList;

AstInfo* astInfo = 0;
SymbolTable* symbolTable = 0;

AstValue::AstValue(const string& value) : AstNode(), m_value(value)
{

}

AstNodeType AstValue::nodeType() const
{
    return Value;
}

string AstValue::stringValue() const
{
    return m_value;
}

AstValue* AstValue::copy()
{
    return new AstValue(m_value);
}

AstMultisetValue::AstMultisetValue() : AstValue(""), m_values()
{

}

AstMultisetValue::AstMultisetValue(const AstMultisetValue& other) :
    AstValue(""),
    m_values(other.m_values)
{

}

AstNodeType AstMultisetValue::nodeType() const
{
    return MultisetValue;
}

string AstMultisetValue::stringValue() const
{
    string ret;

    for(PairList::const_iterator it = m_values.begin();
        it != m_values.end(); ++it)
    {
        pair<string, string> value = *it;

        const size_t bSize = value.first.length() + value.second.length() + 6;
        char* buffer = new char[bSize];
        sprintf(buffer, "%s`%s ++", value.first.c_str(), value.second.c_str());
        ret += string(buffer);
        delete buffer;
    }

    ret = ret.substr(0, ret.length() - 3);

    return ret;
}

AstValue* AstMultisetValue::copy()
{
    return new AstMultisetValue(*this);
}

void AstMultisetValue::addValue(const string& mul, const string& value)
{
    m_values.push_back(std::make_pair(mul, value));
}

AstIdentifier::AstIdentifier(const string& identifier) : AstNode(),
    m_identifier(identifier)
{

}

AstNodeType AstIdentifier::nodeType() const
{
    return Identifier;
}

string AstIdentifier::stringValue() const
{
    return m_identifier;
}

AstIdentifier* AstIdentifier::copy()
{
    return new AstIdentifier(m_identifier);
}

AstNodeType AstBool::nodeType() const
{
    return Bool;
}
string AstBool::stringValue() const
{
    return "bool";
}

AstType* AstBool::copy()
{
    return new AstBool();
}

AstBoolWithConstraints::AstBoolWithConstraints() : AstBool(), m_constraints()
{

}

AstBoolWithConstraints::AstBoolWithConstraints(
    const list<string>& constraints) : AstBool(), m_constraints(constraints)
{

}

AstNodeType AstBoolWithConstraints::nodeType() const
{
    return BoolWithConstraints;
}

string AstBoolWithConstraints::stringValue() const
{
    string ret = "bool";

    if (m_constraints.size() > 0)
    {
        ret += " with ";
    }

    for(list<string>::const_iterator it = m_constraints.begin();
        it != m_constraints.end(); ++it)
    {
        string constraint = *it;

        const size_t bSize = constraint.length() + 6;
        char* buffer = new char[bSize];
        sprintf(buffer, "%s and ", constraint.c_str());
        ret += string(buffer);
        delete buffer;
    }

    if (m_constraints.size() > 0)
    {
        ret = ret.substr(0, ret.length() - 5);
    }

    return ret;
}

AstType* AstBoolWithConstraints::copy()
{
    return new AstBoolWithConstraints(m_constraints);
}

void AstBoolWithConstraints::addConstraint(const string& constraint)
{
    m_constraints.push_back(constraint);
}

list<string> AstBoolWithConstraints::constraints() const
{
    return m_constraints;
}

AstNodeType AstInt::nodeType() const
{
    return Int;
}

string AstInt::stringValue() const
{
    return "int";
}

AstType* AstInt::copy()
{
    return new AstInt();
}

AstIntWithConstraints::AstIntWithConstraints() : AstInt(), m_constraints()
{

}

AstIntWithConstraints::AstIntWithConstraints(
    const list<string>& constraints) : AstInt(), m_constraints(constraints)
{

}

AstNodeType AstIntWithConstraints::nodeType() const
{
    return IntWithConstraints;
}

string AstIntWithConstraints::stringValue() const
{
    string ret = "int";

    if (m_constraints.size() > 0)
    {
        ret += " with ";
    }

    for(list<string>::const_iterator it = m_constraints.begin();
        it != m_constraints.end(); ++it)
    {
        string constraint = *it;

        const size_t bSize = constraint.length() + 6;
        char* buffer = new char[bSize];
        sprintf(buffer, "%s and ", constraint.c_str());
        ret += string(buffer);
        delete buffer;
    }

    if (m_constraints.size() > 0)
    {
        ret = ret.substr(0, ret.length() - 5);
    }

    return ret;
}

AstType* AstIntWithConstraints::copy()
{
    return new AstIntWithConstraints(m_constraints);
}

void AstIntWithConstraints::addConstraint(const string& constraint)
{
    m_constraints.push_back(constraint);
}

list<string> AstIntWithConstraints::constraints() const
{
    return m_constraints;
}

AstNodeType AstString::nodeType() const
{
    return String;
}

string AstString::stringValue() const
{
    return "string";
}

AstType* AstString::copy()
{
    return new AstString();
}

AstStringWithConstraints::AstStringWithConstraints() : AstString(), m_constraints()
{

}

AstStringWithConstraints::AstStringWithConstraints(
    const list<string>& constraints) : AstString(), m_constraints(constraints)
{

}

AstNodeType AstStringWithConstraints::nodeType() const
{
    return StringWithConstraints;
}

string AstStringWithConstraints::stringValue() const
{
    string ret = "string";

    if (m_constraints.size() > 0)
    {
        ret += " with ";
    }

    for(list<string>::const_iterator it = m_constraints.begin();
        it != m_constraints.end(); ++it)
    {
        string constraint = *it;

        const size_t bSize = constraint.length() + 6;
        char* buffer = new char[bSize];
        sprintf(buffer, "%s and ", constraint.c_str());
        ret += string(buffer);
        delete buffer;
    }

    if (m_constraints.size() > 0)
    {
        ret = ret.substr(0, ret.length() - 5);
    }

    return ret;
}

AstType* AstStringWithConstraints::copy()
{
    return new AstStringWithConstraints(m_constraints);
}

void AstStringWithConstraints::addConstraint(const string& constraint)
{
    m_constraints.push_back(constraint);
}

list<string> AstStringWithConstraints::constraints() const
{
    return m_constraints;
}

AstNodeType AstUnit::nodeType() const
{
    return Unit;
}

string AstUnit::stringValue() const
{
    return "unit";
}

AstType* AstUnit::copy()
{
    return new AstUnit();
}

AstUnitWithConstraints::AstUnitWithConstraints() : AstUnit(), m_constraints()
{

}

AstUnitWithConstraints::AstUnitWithConstraints(
    const list<string>& constraints) : AstUnit(), m_constraints(constraints)
{

}

AstNodeType AstUnitWithConstraints::nodeType() const
{
    return UnitWithConstraints;
}

string AstUnitWithConstraints::stringValue() const
{
    string ret = "unit";

    if (m_constraints.size() > 0)
    {
        ret += " with ";
    }

    for(list<string>::const_iterator it = m_constraints.begin();
        it != m_constraints.end(); ++it)
    {
        string constraint = *it;

        const size_t bSize = constraint.length() + 6;
        char* buffer = new char[bSize];
        sprintf(buffer, "%s and ", constraint.c_str());
        ret += string(buffer);
        delete buffer;
    }

    if (m_constraints.size() > 0)
    {
        ret = ret.substr(0, ret.length() - 5);
    }

    return ret;
}

AstType* AstUnitWithConstraints::copy()
{
    return new AstUnitWithConstraints(m_constraints);
}

void AstUnitWithConstraints::addConstraint(const string& constraint)
{
    m_constraints.push_back(constraint);
}

list<string> AstUnitWithConstraints::constraints() const
{
    return m_constraints;
}

AstNodeType AstEnum::nodeType() const
{
    return Enum;
}

string AstEnum::stringValue() const
{
    return "enum";
}

AstType* AstEnum::copy()
{
    return new AstEnum();
}

AstEnumWithConstraints::AstEnumWithConstraints() : AstEnum(), m_constraints()
{

}

AstEnumWithConstraints::AstEnumWithConstraints(
    const list<string>& constraints) : AstEnum(), m_constraints(constraints)
{

}

AstNodeType AstEnumWithConstraints::nodeType() const
{
    return EnumWithConstraints;
}

string AstEnumWithConstraints::stringValue() const
{
    string ret;

    if (m_constraints.size() > 0)
    {
        ret += " with ";
    }

    for(list<string>::const_iterator it = m_constraints.begin();
        it != m_constraints.end(); ++it)
    {
        string constraint = *it;

        const size_t bSize = constraint.length() + 4;
        char* buffer = new char[bSize];
        sprintf(buffer, "%s | ", constraint.c_str());
        ret += string(buffer);
        delete buffer;
    }

    if (m_constraints.size() > 0)
    {
        ret = ret.substr(0, ret.length() - 3);
    }

    return ret;
}

AstType* AstEnumWithConstraints::copy()
{
    return new AstEnumWithConstraints(m_constraints);
}

void AstEnumWithConstraints::addConstraint(const string& constraint)
{
    m_constraints.push_back(constraint);
}

list<string> AstEnumWithConstraints::constraints() const
{
    return m_constraints;
}

AstValueDeclaration::AstValueDeclaration(AstIdentifier* identifier,
    AstValue* value) : AstDeclaration(),
        m_identifier(identifier),
        m_value(value)
{

}

AstValueDeclaration::AstValueDeclaration(AstValueDeclaration& other) :
    AstDeclaration(),
    m_identifier(other.m_identifier->copy()),
    m_value(other.m_value->copy())
{

}

AstValueDeclaration& AstValueDeclaration::operator=(
    const AstValueDeclaration& other)
{
    if (this != &other)
    {
        m_identifier = other.m_identifier->copy();
        m_value = other.m_value->copy();
    }

    return *this;
}

AstValueDeclaration::~AstValueDeclaration()
{
    delete m_identifier;
    delete m_value;
}

AstNodeType AstValueDeclaration::nodeType() const
{
    return ValueDeclaration;
}

string AstValueDeclaration::stringValue() const
{
    string ret;

    const string idS = m_identifier->stringValue();
    const string valS = m_value->stringValue();

    const size_t bSize = idS.length() +
        valS.length() + 8;
    char* buffer = new char[bSize];
    sprintf(buffer, "val %s = %s", idS.c_str(),
        valS.c_str());

    ret = buffer;
    delete buffer;

    return ret;
}

AstStatement* AstValueDeclaration::copy()
{
    return new AstValueDeclaration(*this);
}

const AstIdentifier& AstValueDeclaration::identifier() const
{
    return *m_identifier;
}
const AstValue& AstValueDeclaration::value() const
{
    return *m_value;
}

AstVariableDeclaration::AstVariableDeclaration(AstIdentifier* identifier,
    AstType* type) : AstDeclaration(),
        m_identifier(identifier),
        m_type(type)
{

}

AstVariableDeclaration::AstVariableDeclaration(AstVariableDeclaration& other) :
    AstDeclaration(),
    m_identifier(other.m_identifier->copy()),
    m_type(other.m_type->copy())
{

}

AstVariableDeclaration& AstVariableDeclaration::operator=(
    const AstVariableDeclaration& other)
{
    if (this != &other)
    {
        m_identifier = other.m_identifier->copy();
        m_type = other.m_type->copy();
    }

    return *this;
}

AstVariableDeclaration::~AstVariableDeclaration()
{
    delete m_identifier;
    delete m_type;
}

AstNodeType AstVariableDeclaration::nodeType() const
{
    return VariableDeclaration;
}

string AstVariableDeclaration::stringValue() const
{
    string ret;

    const string idS = m_identifier->stringValue();
    const string typeS = m_type->stringValue();

    const size_t bSize = idS.length() +
        typeS.length() + 8;
    char* buffer = new char[bSize];
    sprintf(buffer, "var %s : %s", idS.c_str(),
        typeS.c_str());

    ret = buffer;
    delete buffer;

    return ret;
}

AstStatement* AstVariableDeclaration::copy()
{
    return new AstVariableDeclaration(*this);
}

const AstIdentifier& AstVariableDeclaration::identifier() const
{
    return *m_identifier;
}
const AstType& AstVariableDeclaration::type() const
{
    return *m_type;
}

AstColsetDeclaration::AstColsetDeclaration(AstIdentifier* identifier,
    AstType* type) : AstDeclaration(),
        m_identifier(identifier),
        m_type(type)
{

}

AstColsetDeclaration::AstColsetDeclaration(AstColsetDeclaration& other) :
    AstDeclaration(),
    m_identifier(other.m_identifier->copy()),
    m_type(other.m_type->copy())
{

}

AstColsetDeclaration& AstColsetDeclaration::operator=(
    const AstColsetDeclaration& other)
{
    if (this != &other)
    {
        m_identifier = other.m_identifier->copy();
        m_type = other.m_type->copy();
    }

    return *this;
}

AstColsetDeclaration::~AstColsetDeclaration()
{
    delete m_identifier;
    delete m_type;
}

AstNodeType AstColsetDeclaration::nodeType() const
{
    return ColsetDeclaration;
}

string AstColsetDeclaration::stringValue() const
{
    string ret;

    const string idS = m_identifier->stringValue();
    const string typeS = m_type->stringValue();

    const size_t bSize = idS.length() +
        typeS.length() + 8;
    char* buffer = new char[bSize];
    sprintf(buffer, "colset %s = %s", idS.c_str(),
        typeS.c_str());

    ret = buffer;
    delete buffer;

    return ret;
}

AstStatement* AstColsetDeclaration::copy()
{
    return new AstColsetDeclaration(*this);
}

const AstIdentifier& AstColsetDeclaration::identifier() const
{
    return *m_identifier;
}
const AstType& AstColsetDeclaration::type() const
{
    return *m_type;
}

AstOperator::AstOperator(Operator op) : AstNode(),
    m_operator(op)
{

}

AstNodeType AstOperator::nodeType() const
{
    AstNodeType type;

    switch (m_operator)
    {
    case OperatorEqual:
        type = OpEqual;
    case OperatorNotEqual:
        type = OpNotEqual;
    case OperatorLesserThan:
        type = OpLesserThan;
    case OperatorLesserThanEqual:
        type = OpLesserThanEqual;
    case OperatorGreaterThan:
        type = OpGreaterThan;
    case OperatorGreaterThanEqual:
        type = OpGreaterThanEqual;
    }

    return type;
}

string AstOperator::stringValue() const
{
    string ret;

    switch (m_operator)
    {
    case OperatorEqual:
        ret = "=";
    case OperatorNotEqual:
        ret = "<>";
    case OperatorLesserThan:
        ret = "<";
    case OperatorLesserThanEqual:
        ret = "<=";
    case OperatorGreaterThan:
        ret = ">";
    case OperatorGreaterThanEqual:
        ret = ">=";
    }

    return ret;
}

AstOperator* AstOperator::copy()
{
    return new AstOperator(m_operator);
}

AstPlaceParams::AstPlaceParams(AstType* colset, const string& name,
    AstValue* marking) : AstNode(),
        m_colset(colset),
        m_name(name),
        m_marking(marking)
{

}

AstPlaceParams::AstPlaceParams(const AstPlaceParams& other) :
    AstNode(),
    m_colset(other.m_colset->copy()),
    m_name(other.m_name),
    m_marking(other.m_marking != 0 ? other.m_marking->copy() : 0)
{

}

AstPlaceParams& AstPlaceParams::operator=(const AstPlaceParams& other)
{
    if (this != &other)
    {
        m_colset = other.m_colset->copy();
        m_name = other.m_name;
        m_marking = other.m_marking != 0 ? other.m_marking->copy() : 0;
    }

    return *this;
}

AstPlaceParams::~AstPlaceParams()
{
    delete m_colset;
    delete m_marking;
}

AstNodeType AstPlaceParams::nodeType() const
{
    return PlaceParams;
}

string AstPlaceParams::stringValue() const
{
    string ret;

    const string cS = m_colset->stringValue();
    const string mS = m_marking != 0 ? m_marking->stringValue() : "0";

    const size_t bSize = cS.length() + m_name.length() +
        mS.length() + 10;
    char* buffer = new char[bSize];
    sprintf(buffer, "[%s, %s, %s]", cS.c_str(),
        m_name.c_str(),
        mS.c_str());

    ret = string(buffer);
    delete buffer;

    return ret;
}

AstPlaceParams* AstPlaceParams::copy()
{
    return new AstPlaceParams(*this);
}

const AstType& AstPlaceParams::colset() const
{
    return *m_colset;
}

string AstPlaceParams::name() const
{
    return m_name;
}

const AstValue& AstPlaceParams::marking() const
{
    return *m_marking;
}

AstTransitionParams::AstTransitionParams(const string& loperand,
    AstOperator* op,
    const string& roperand) : AstNode(),
        m_loperand(loperand),
        m_roperand(roperand),
        m_roperandValued(0),
        m_op(op)
{

}

AstTransitionParams::AstTransitionParams(const string& loperand,
    AstOperator* op,
    AstValue* roperand) : AstNode(),
        m_loperand(loperand),
        m_roperand(""),
        m_roperandValued(roperand),
        m_op(op)
{

}

AstTransitionParams::AstTransitionParams(const AstTransitionParams& other) :
    AstNode(),
    m_loperand(other.m_loperand),
    m_roperand(other.m_roperand),
    m_roperandValued(other.m_roperandValued != 0 ?
        other.m_roperandValued->copy() : 0),
    m_op(other.m_op != 0 ? other.m_op->copy() : 0)
{

}

AstTransitionParams& AstTransitionParams::operator=(
    const AstTransitionParams& other)
{
    if (this != &other)
    {
        m_loperand = other.m_loperand;
        m_roperand = other.m_roperand;
        m_roperandValued = other.m_roperandValued != 0 ?
            other.m_roperandValued->copy() : 0;
        m_op = other.m_op != 0 ? other.m_op->copy() : 0;
    }

    return *this;
}

AstTransitionParams::~AstTransitionParams()
{
    delete m_roperandValued;
    delete m_op;
}

AstNodeType AstTransitionParams::nodeType() const
{
    return TransitionParams;
}

string AstTransitionParams::stringValue() const
{
    string ret;

    if (isEmpty())
    {
        ret = "[]";
    }
    else
    {  
        const string opS = m_op->stringValue();
        const string ropS = isRightOperandValued() ?
            m_roperandValued->stringValue() : m_roperand;

        const size_t bSize = m_loperand.length() + opS.length() +
            ropS.length() + 10;
        char* buffer = new char[bSize];
        sprintf(buffer, "[%s %s %s]", m_loperand.c_str(),
            opS.c_str(),
            ropS.c_str());

        ret = string(buffer);
        delete buffer;
    }

    return ret;
}

AstTransitionParams* AstTransitionParams::copy()
{
    return new AstTransitionParams(*this);
}

string AstTransitionParams::leftOperand() const
{
    return m_loperand;
}

string AstTransitionParams::rightOperand() const
{
    return m_roperand;
}

const AstValue& AstTransitionParams::rightOperandValued() const
{
    return *m_roperandValued;
}

const AstOperator& AstTransitionParams::op() const
{
    return *m_op;
}

bool AstTransitionParams::isEmpty() const
{
    return m_loperand.length() == 0;
}

bool AstTransitionParams::isRightOperandValued() const
{
    return m_roperandValued != 0;
}

AstPlace::AstPlace(const string& id,
    AstPlaceParams* params,
    bool createNew) : AstNode(),
        m_id(id),
        m_params(params),
        m_createNew(createNew)
{

}

AstPlace::AstPlace(const AstPlace& other) :
    AstNode(),
    m_id(other.m_id),
    m_params(other.m_params->copy()),
    m_createNew(other.m_createNew)
{

}

AstPlace& AstPlace::operator=(
    const AstPlace& other)
{
    if (this != &other)
    {
        m_id = other.m_id;
        m_params = other.m_params->copy();
        m_createNew = other.m_createNew;
    }

    return *this;
}

AstPlace::~AstPlace()
{
    delete m_params;
}

AstNodeType AstPlace::nodeType() const
{
    return Place;
}

string AstPlace::stringValue() const
{
    string ret;

    const string pS = m_createNew ? "_np" : "_p";
    const string parS = m_params->stringValue();

    const size_t bSize = pS.length() + m_id.length() +
        parS.length() + 5;
    char* buffer = new char[bSize];
    sprintf(buffer, "%s(%s)%s", pS.c_str(),
        m_id.c_str(),
        parS.c_str());

    ret = string(buffer);
    delete buffer;

    return ret;
}

AstPlace* AstPlace::copy()
{
    return new AstPlace(*this);
}

string AstPlace::id() const
{
    return m_id;
}

const AstPlaceParams& AstPlace::params() const
{
    return *m_params;
}

bool AstPlace::createNew() const
{
    return m_createNew;
}

AstTransition::AstTransition(const string& id,
    AstTransitionParams* params,
    bool createNew) : AstNode(),
        m_id(id),
        m_params(params),
        m_createNew(createNew)
{

}

AstTransition::AstTransition(const AstTransition& other) :
    AstNode(),
    m_id(other.m_id),
    m_params(other.m_params->copy()),
    m_createNew(other.m_createNew)
{

}

AstTransition& AstTransition::operator=(
    const AstTransition& other)
{
    if (this != &other)
    {
        m_id = other.m_id;
        m_params = other.m_params->copy();
        m_createNew = other.m_createNew;
    }

    return *this;
}

AstTransition::~AstTransition()
{
    delete m_params;
}

AstNodeType AstTransition::nodeType() const
{
    return Transition;
}

string AstTransition::stringValue() const
{
    string ret;

    const string tS = m_createNew ? "_nt" : "_t";
    const string parS = m_params->stringValue();

    const size_t bSize = tS.length() + m_id.length() +
        parS.length() + 5;
    char* buffer = new char[bSize];
    sprintf(buffer, "%s(%s)%s", tS.c_str(),
        m_id.c_str(),
        parS.c_str());

    ret = string(buffer);
    delete buffer;

    return ret;
}

AstTransition* AstTransition::copy()
{
    return new AstTransition(*this);
}

string AstTransition::id() const
{
    return m_id;
}

const AstTransitionParams& AstTransition::params() const
{
    return *m_params;
}

bool AstTransition::createNew() const
{
    return m_createNew;
}

AstArcExpression::AstArcExpression(AstValue* value) : AstNode(),
    m_value(value->copy())
{

}

AstArcExpression::AstArcExpression(const AstArcExpression& other) :
    AstNode(),
    m_value(other.m_value->copy())
{

}

AstArcExpression& AstArcExpression::operator=(
    const AstArcExpression& other)
{
    if (this != &other)
    {
        m_value = other.m_value->copy();
    }

    return *this;
}

AstArcExpression::~AstArcExpression()
{
    delete m_value;
}

AstNodeType AstArcExpression::nodeType() const
{
    return ArcExpression;
}

string AstArcExpression::stringValue() const
{
    string ret;

    const string valS = m_value->stringValue();

    const size_t bSize = valS.length() + 3;
    char* buffer = new char[bSize];
    sprintf(buffer, "[%s]", valS.c_str());

    ret = string(buffer);
    delete buffer;

    return ret;
}

AstArcExpression* AstArcExpression::copy()
{
    return new AstArcExpression(*this);
}

const AstValue& AstArcExpression::value() const
{
    return *m_value;
}

AstConnection::AstConnection(AstPlace* place, AstArcExpression* arcExpression,
    AstTransition* transition) : AstStatement(),
        m_place(place),
        m_transition(transition),
        m_arcExpression(arcExpression),
        m_direction(PlaceToTransition)
{

}

AstConnection::AstConnection(AstTransition* transition,
    AstArcExpression* arcExpression,
    AstPlace* place) : AstStatement(),
        m_place(place),
        m_transition(transition),
        m_arcExpression(arcExpression),
        m_direction(TransitionToPlace)
{

}

AstConnection::AstConnection(const AstConnection& other) : AstStatement(),
    m_place(other.m_place->copy()),
    m_transition(other.m_transition->copy()),
    m_arcExpression(other.m_arcExpression->copy()),
    m_direction(other.m_direction)
{

}

AstConnection& AstConnection::operator=(const AstConnection& other)
{
    if (this != &other)
    {
        m_place = other.m_place->copy();
        m_transition = other.m_transition->copy();
        m_arcExpression = other.m_arcExpression->copy();
        m_direction = other.m_direction;
    }

    return *this;
}

AstConnection::~AstConnection()
{
    delete m_place;
    delete m_transition;
    delete m_arcExpression;
}

AstNodeType AstConnection::nodeType() const
{
    return Connection;
}

string AstConnection::stringValue() const
{
    string ret;

    const string pS = m_place->stringValue();
    const string tS = m_transition->stringValue();
    const string fS = m_direction == PlaceToTransition ? pS : tS;
    const string eS = m_arcExpression->stringValue();
    const string sS = m_direction == PlaceToTransition ? tS : pS;

    const size_t bSize = fS.length() + eS.length() + sS.length() + 6;
    char* buffer = new char[bSize];
    sprintf(buffer, "%s-%s->%s", fS.c_str(),
        eS.c_str(),
        sS.c_str());

    ret = string(buffer);
    delete buffer;

    return ret;
}

AstStatement* AstConnection::copy()
{
    return new AstConnection(*this);
}

const AstPlace& AstConnection::place() const
{
    return *m_place;
}

const AstTransition& AstConnection::transition() const
{
    return *m_transition;
}

const AstArcExpression& AstConnection::arcExpression() const
{
    return *m_arcExpression;
}

Direction AstConnection::direction() const
{
    return m_direction;
}

AstCodeBlock::AstCodeBlock() : AstNode(), m_statements()
{

}

AstCodeBlock::AstCodeBlock(AstCodeBlock& other) : AstNode(), m_statements()
{   
    for(list<AstStatement*>::iterator it = other.m_statements.begin();
        it != other.m_statements.end(); ++it)
    {
        AstStatement* stmt = *it;
        m_statements.push_back(stmt->copy());
    }
}

AstCodeBlock& AstCodeBlock::operator=(const AstCodeBlock& other)
{
    if (this != &other)
    {
        for(list<AstStatement*>::const_iterator it = other.m_statements.begin();
            it != other.m_statements.end(); ++it)
        {
            AstStatement* stmt = *it;
            m_statements.push_back(stmt->copy());
        }
    }

    return *this;
}

AstCodeBlock::~AstCodeBlock()
{
    for(list<AstStatement*>::const_iterator it = m_statements.begin();
        it != m_statements.end(); ++it)
    {
        AstStatement* stmt = *it;

        delete stmt;
    }
}

AstNodeType AstCodeBlock::nodeType() const
{
    return Constraints;
}

string AstCodeBlock::stringValue() const
{
    string ret;

    for(list<AstStatement*>::const_iterator it = m_statements.begin();
        it != m_statements.end(); ++it)
    {
        AstStatement* stmt = *it;

        const string sS = stmt->stringValue();

        const size_t bSize = sS.length() + 3;
        char* buffer = new char[bSize];
        sprintf(buffer, "%s\n", sS.c_str());

        ret += string(buffer);
        delete buffer;
    }

    return ret;
}

void AstCodeBlock::addStatement(AstStatement* statement)
{
    m_statements.push_back(statement);
}

void AstCodeBlock::insertStatement(int index, AstStatement* statement)
{
    list<AstStatement* >::iterator it = m_statements.begin();

    advance(it, index);

    m_statements.insert(it, statement);
}

list<AstStatement*> AstCodeBlock::statements() const
{
    return m_statements;
}

AstInfo* AstInfo::i()
{
    if (astInfo == 0)
    {
        astInfo = new AstInfo();
    }

    return astInfo;
}

void AstInfo::destroy()
{
    delete astInfo;
    astInfo = 0;
}

void AstInfo::astHandleError(const std::string& s)
{
    if (m_errors.size() > 0)
    {
        list<AstError>::iterator it = m_errors.end();
        --it;

        AstError& err = *it;
        if (err.Line == m_currentLine && err.Column == m_currentColumn)
        {
            err.ParseError = s;
        }
        else
        {
            AstError err;
            err.Line = m_currentLine;
            err.Column = m_currentColumn;
            err.ParseError = s;

            m_errors.push_back(err);
        }
    }
    else
    {
        AstError err;
        err.Line = m_currentLine;
        err.Column = m_currentColumn;
        err.ParseError = s;

        m_errors.push_back(err);
    }
}

void AstInfo::astHandleLexError(const std::string& s)
{
    AstError err;
    err.Line = m_currentLine;
    err.Column = m_currentColumn;
    err.LexError = s;

    m_errors.push_back(err);
}

void AstInfo::handleNewLine()
{
    m_currentColumn = 0;
    ++m_currentLine;
}

void AstInfo::handleColumnShift()
{
    ++m_currentColumn;
}

list<AstError> AstInfo::errors() const
{
    return m_errors;
}

AstInfo::AstInfo() :
    m_currentLine(0),
    m_currentColumn(0),
    m_errors()
{

}

AstInfo::~AstInfo()
{

}


SymbolTable* SymbolTable::i()
{
    if (symbolTable == 0)
    {
        symbolTable = new SymbolTable();
    }

    return symbolTable;
}

void SymbolTable::destroy()
{
    delete symbolTable;
    symbolTable = 0;
}

bool SymbolTable::addSymbol(const std::string& id, AstStatement* stmt)
{
    bool ret = m_symbols.find(id) == m_symbols.end();

    if (ret)
    {
        SymbolInfo info;
        info.Statement = stmt;
        info.Column = AstInfo::i()->m_currentColumn;
        info.Line = AstInfo::i()->m_currentLine;

        m_symbols[id] = info;
    }

    return ret;
}

bool SymbolTable::lookupsymbol(const std::string& id)
{
    bool ret = m_symbols.find(id) != m_symbols.end();

    return ret;
}

SymbolTable::SymbolTable() :
    m_symbols()
{

}

SymbolTable::~SymbolTable()
{

}
